diff --git a/Cargo.lock b/Cargo.lock
index b05a3c47020a4108c75152d25736d9f744448f16..227e8228af18f15c2344458c3a65aac88539ad32 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,9 +2,9 @@
 # It is not intended for manual editing.
 [[package]]
 name = "addr2line"
-version = "0.14.0"
+version = "0.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
+checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7"
 dependencies = [
  "gimli",
 ]
@@ -44,9 +44,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
 
 [[package]]
 name = "assign"
-version = "1.1.0"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4af5687fe33aec5e70ef14caac5e0d363e335e5e5d6385fb75978d0c241b1d67"
+checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002"
 
 [[package]]
 name = "async-trait"
@@ -369,9 +369,9 @@ checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
 
 [[package]]
 name = "dtoa"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
+checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e"
 
 [[package]]
 name = "either"
@@ -576,11 +576,11 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.1.15"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "libc",
  "wasi 0.9.0+wasi-snapshot-preview1",
 ]
@@ -834,9 +834,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
 
 [[package]]
 name = "jpeg-decoder"
@@ -1046,9 +1046,9 @@ dependencies = [
 
 [[package]]
 name = "native-tls"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fcc7939b5edc4e4f86b1b4a04bb1498afaaf871b1a6691838ed06fcb48d3a3f"
+checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4"
 dependencies = [
  "lazy_static",
  "libc",
@@ -1149,9 +1149,9 @@ checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
 
 [[package]]
 name = "openssl"
-version = "0.10.31"
+version = "0.10.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d008f51b1acffa0d3450a68606e6a51c123012edaacb0f4e1426bd978869187"
+checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70"
 dependencies = [
  "bitflags",
  "cfg-if 1.0.0",
@@ -1178,9 +1178,9 @@ dependencies = [
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.59"
+version = "0.9.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de52d8eabd217311538a39bba130d7dea1f1e118010fee7a033d966845e7d5fe"
+checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6"
 dependencies = [
  "autocfg",
  "cc",
@@ -1407,7 +1407,7 @@ version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
 dependencies = [
- "getrandom 0.1.15",
+ "getrandom 0.1.16",
  "libc",
  "rand_chacha 0.2.2",
  "rand_core 0.5.1",
@@ -1452,7 +1452,7 @@ version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
 dependencies = [
- "getrandom 0.1.15",
+ "getrandom 0.1.16",
 ]
 
 [[package]]
@@ -1494,25 +1494,25 @@ version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
 dependencies = [
- "getrandom 0.1.15",
+ "getrandom 0.1.16",
  "redox_syscall",
  "rust-argon2",
 ]
 
 [[package]]
 name = "ref-cast"
-version = "1.0.3"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e17626b2f4bcf35b84bf379072a66e28cfe5c3c6ae58b38e4914bb8891dabece"
+checksum = "300f2a835d808734ee295d45007adacb9ebb29dd3ae2424acfa17930cae541da"
 dependencies = [
  "ref-cast-impl",
 ]
 
 [[package]]
 name = "ref-cast-impl"
-version = "1.0.3"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c523ccaed8ac4b0288948849a350b37d3035827413c458b6a40ddb614bb4f72"
+checksum = "4c38e3aecd2b21cb3959637b883bb3714bc7e43f0268b9a29d3743ee3e55cdd2"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2005,9 +2005,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.60"
+version = "1.0.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
+checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
 dependencies = [
  "itoa",
  "ryu",
@@ -2088,9 +2088,9 @@ dependencies = [
 
 [[package]]
 name = "smallvec"
-version = "1.5.1"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75"
+checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0"
 
 [[package]]
 name = "socket2"
@@ -2111,9 +2111,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
 [[package]]
 name = "standback"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf906c8b8fc3f6ecd1046e01da1d8ddec83e48c8b08b84dcc02b585a6bedf5a8"
+checksum = "c66a8cff4fa24853fdf6b51f75c6d7f8206d7c75cab4e467bcd7f25c2b1febe0"
 dependencies = [
  "version_check",
 ]
@@ -2127,7 +2127,7 @@ checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483"
 [[package]]
 name = "state-res"
 version = "0.1.0"
-source = "git+https://github.com/ruma/state-res?branch=event-trait#9b96204571521e216a618d102459d662c52a2210"
+source = "git+https://github.com/ruma/state-res?branch=event-trait#bfadbdf57e26f26c2ea5b2ed50ce3e5f6fb914cd"
 dependencies = [
  "itertools",
  "maplit",
@@ -2189,9 +2189,9 @@ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
 
 [[package]]
 name = "syn"
-version = "1.0.55"
+version = "1.0.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a"
+checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2214,18 +2214,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.22"
+version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
+checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.22"
+version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
+checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2752,9 +2752,9 @@ dependencies = [
 
 [[package]]
 name = "yaml-rust"
-version = "0.4.4"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
 dependencies = [
  "linked-hash-map",
 ]
diff --git a/src/database/rooms.rs b/src/database/rooms.rs
index f0129c6b7a73d4c59379103fdbeb6fc2cf0c4c3c..ef76c398d0885903e9320dae5b7cd08b9df40ad1 100644
--- a/src/database/rooms.rs
+++ b/src/database/rooms.rs
@@ -802,32 +802,9 @@ pub fn build_and_append_pdu(
                         ))?)?
                         .map(Arc::new);
                     event_auth::valid_membership_change(
-                        // TODO this is a bit of a hack but not sure how to have a type
-                        // declared in `state_res` crate easily convert to/from conduit::PduEvent
-                        &Arc::new(PduEvent {
-                            event_id: ruma::event_id!("$thiswillbefilledinlater"),
-                            room_id: room_id.clone(),
-                            sender: sender.clone(),
-                            origin_server_ts: utils::millis_since_unix_epoch()
-                                .try_into()
-                                .expect("time is valid"),
-                            kind: event_type,
-                            content,
-                            state_key: Some(state_key.clone()),
-                            prev_events,
-                            depth: (prev_events.len() as u32).into(),
-                            auth_events: auth_events
-                                .into_iter()
-                                .map(|(_, pdu)| pdu.event_id)
-                                .collect(),
-                            redacts,
-                            unsigned: unsigned
-                                .map_or_else(BTreeMap::new, |m| m.into_iter().collect()),
-                            hashes: ruma::events::pdu::EventHash {
-                                sha256: "aaa".to_owned(),
-                            },
-                            signatures: BTreeMap::new(),
-                        }),
+                        Some(state_key.as_str()),
+                        &sender,
+                        content.clone(),
                         prev_event,
                         None, // TODO: third party invite
                         &auth_events
diff --git a/src/pdu.rs b/src/pdu.rs
index c764700ef5af882d903a875c32a68caa6508c00f..29973176528e9fe35f90e188725c8cf36e31de18 100644
--- a/src/pdu.rs
+++ b/src/pdu.rs
@@ -229,7 +229,7 @@ pub fn convert_to_outgoing_federation_event(
 
     pub fn from_id_val(
         event_id: &EventId,
-        json: CanonicalJsonObject,
+        mut json: CanonicalJsonObject,
     ) -> Result<Self, serde_json::Error> {
         json.insert(
             "event_id".to_string(),
diff --git a/src/server_server.rs b/src/server_server.rs
index 58d85b14d8aa6c0eee0d67aa7f6f9ea32ab5a991..3c4308cdb25de53080dff54f29b58aabac3c1bf1 100644
--- a/src/server_server.rs
+++ b/src/server_server.rs
@@ -1,4 +1,4 @@
-use crate::{client_server, utils, ConduitResult, Database, Error, PduEvent, Result, Ruma};
+use crate::{client_server, pdu, utils, ConduitResult, Database, Error, PduEvent, Result, Ruma};
 use get_profile_information::v1::ProfileField;
 use http::header::{HeaderValue, AUTHORIZATION, HOST};
 use log::{error, info, warn};
@@ -11,13 +11,15 @@
                 get_server_keys, get_server_version::v1 as get_server_version, ServerSigningKeys,
                 VerifyKey,
             },
-            event::{get_missing_events, get_room_state, get_room_state_ids},
+            event::{get_event, get_missing_events, get_room_state, get_room_state_ids},
             query::get_profile_information,
             transactions::send_transaction_message,
         },
         OutgoingRequest,
     },
     directory::{IncomingFilter, IncomingRoomNetwork},
+    serde::Raw,
+    signatures::{CanonicalJsonObject, PublicKeyMap},
     EventId, RoomId, RoomVersionId, ServerName, ServerSigningKeyId, UserId,
 };
 use state_res::{Event, StateMap};
@@ -578,32 +580,13 @@ pub async fn send_transaction_message_route<'a>(
         let mut pub_key_map = BTreeMap::new();
         pub_key_map.insert("domain".to_string(), pub_key_set);
 
-        let value =
-            match ruma::signatures::verify_event(&pub_key_map, &value, &RoomVersionId::Version6) {
-                Ok(ver) => {
-                    if let ruma::signatures::Verified::Signatures = ver {
-                        match ruma::signatures::redact(&value, &RoomVersionId::Version6) {
-                            Ok(obj) => obj,
-                            Err(_) => {
-                                resolved_map
-                                    .insert(event_id, Err("Room is unknown to this server".into()));
-                                continue;
-                            }
-                        }
-                    } else {
-                        value
-                    }
-                }
-                Err(_e) => {
-                    resolved_map.insert(event_id, Err("Room is unknown to this server".into()));
-                    continue;
-                }
-            };
-
-        let pdu = serde_json::from_value::<PduEvent>(
-            serde_json::to_value(&value).expect("CanonicalJsonObj is a valid JsonValue"),
-        )
-        .expect("all ruma pdus are conduit pdus");
+        let pdu = match signature_and_hash_check(&pub_key_map, value) {
+            Ok(pdu) => pdu,
+            Err(e) => {
+                resolved_map.insert(event_id, Err(e));
+                continue;
+            }
+        };
 
         // If we have no idea about this room skip the PDU
         if !db.rooms.exists(&pdu.room_id)? {
@@ -619,7 +602,10 @@ pub async fn send_transaction_message_route<'a>(
             .map(|id| db.rooms.get_pdu(id).expect("todo").map(Arc::new))
             .flatten();
 
-        // 4.
+        // 4. Passes authorization rules based on the event's auth events, otherwise it is rejected.
+        // TODO: To me this sounds more like the auth_events should be get the pdu.auth_events not
+        // the auth events that would be correct for this pdu. Put another way we should use the auth events
+        // the pdu claims are its auth events
         let auth_events = db.rooms.get_auth_events(
             &pdu.room_id,
             &pdu.kind,
@@ -627,6 +613,12 @@ pub async fn send_transaction_message_route<'a>(
             pdu.state_key.as_deref(),
             pdu.content.clone(),
         )?;
+
+        let mut event_map: state_res::EventMap<Arc<PduEvent>> = auth_events
+            .iter()
+            .map(|(k, v)| (v.event_id().clone(), Arc::new(v.clone())))
+            .collect();
+
         if !state_res::event_auth::auth_check(
             &RoomVersionId::Version6,
             &event,
@@ -635,7 +627,7 @@ pub async fn send_transaction_message_route<'a>(
                 .into_iter()
                 .map(|(k, v)| (k, Arc::new(v)))
                 .collect(),
-            None,
+            None, // TODO: third party invite
         )
         .map_err(|_e| Error::Conflict("Auth check failed"))?
         {
@@ -646,66 +638,38 @@ pub async fn send_transaction_message_route<'a>(
             continue;
         }
 
-        let mut previous_states: Vec<StateMap<Arc<PduEvent>>> = vec![];
-        for id in &pdu.prev_events {
-            if let Some(id) = db.rooms.get_pdu_id(id)? {
-                let state_hash = db
-                    .rooms
-                    .pdu_state_hash(&id)?
-                    .expect("found pdu with no statehash");
-                let state = db
-                    .rooms
-                    .state_full(&pdu.room_id, &state_hash)?
+        let server_name = body.body.origin.clone();
+        let (state_at_event, incoming_auth_events): (StateMap<Arc<PduEvent>>, _) = match db
+            .sending
+            .send_federation_request(
+                &db.globals,
+                server_name.clone(),
+                get_room_state_ids::v1::Request {
+                    room_id: pdu.room_id(),
+                    event_id: pdu.event_id(),
+                },
+            )
+            .await
+        {
+            Ok(res) => {
+                let state = fetch_events(&db, server_name.clone(), &pub_key_map, &res.pdu_ids)
+                    .await?
                     .into_iter()
-                    .map(|((et, sk), ev)| ((et, Some(sk)), Arc::new(ev)))
+                    .map(|pdu| ((pdu.kind.clone(), pdu.state_key.clone()), Arc::new(pdu)))
                     .collect();
-                previous_states.push(state);
-            } else {
-                // fetch the state
-                match db
-                    .sending
-                    .send_federation_request(
-                        &db.globals,
-                        body.body.origin,
-                        get_room_state_ids::v1::Request {
-                            room_id: &pdu.room_id,
-                            event_id: id,
-                        },
-                    )
-                    .await
-                {
-                    Ok(res) => todo!(),
-                    Err(e) => panic!(e),
-                }
-            }
-        }
 
-        // 5. Passes authorization rules based on the state at the event, otherwise it is rejected.
-        let state_at_event = if previous_states.is_empty() {
-            // State is empty
-            Default::default()
-        } else if previous_states.len() == 1 {
-            previous_states[0].clone()
-        } else {
-            match state_res::StateResolution::resolve(
-                &pdu.room_id,
-                &RoomVersionId::Version6,
-                &previous_states
-                    .into_iter()
-                    .map(|map| {
-                        map.into_iter()
-                            .map(|(k, v)| (k, v.event_id.clone()))
-                            .collect::<StateMap<_>>()
-                    })
-                    .collect::<Vec<_>>(),
-                None,
-                &db.rooms,
-            ) {
-                Ok(res) => res
-                    .into_iter()
-                    .map(|(k, v)| (k, Arc::new(db.rooms.get_pdu(&v).unwrap().unwrap())))
-                    .collect(),
-                Err(e) => panic!("{:?}", e),
+                (
+                    state,
+                    fetch_events(&db, server_name.clone(), &pub_key_map, &res.auth_chain_ids)
+                        .await?,
+                )
+            }
+            Err(_) => {
+                resolved_map.insert(
+                    event.event_id().clone(),
+                    Err("Fetching state for event failed".into()),
+                );
+                continue;
             }
         };
 
@@ -713,8 +677,8 @@ pub async fn send_transaction_message_route<'a>(
             &RoomVersionId::Version6,
             &event,
             previous.clone(),
-            state_at_event,
-            None,
+            state_at_event.clone(), // TODO: could this be &state avoid .clone
+            None,                   // TODO: third party invite
         )
         .map_err(|_e| Error::Conflict("Auth check failed"))?
         {
@@ -747,22 +711,7 @@ pub async fn send_transaction_message_route<'a>(
 
                 fork_states.push(state);
             } else {
-                // This is probably an error??
-                match db
-                    .sending
-                    .send_federation_request(
-                        &db.globals,
-                        body.body.origin,
-                        get_room_state_ids::v1::Request {
-                            room_id: &pdu.room_id,
-                            event_id: id,
-                        },
-                    )
-                    .await
-                {
-                    Ok(res) => todo!(),
-                    Err(e) => panic!(e),
-                }
+                todo!("we don't know of a pdu that is part of our known forks OOPS")
             }
         }
 
@@ -773,6 +722,18 @@ pub async fn send_transaction_message_route<'a>(
         } else if fork_states.len() == 1 {
             fork_states[0].clone()
         } else {
+            // Add as much as we can to the `event_map` (less DB hits)
+            event_map.extend(
+                incoming_auth_events
+                    .into_iter()
+                    .map(|pdu| (pdu.event_id().clone(), Arc::new(pdu))),
+            );
+            event_map.extend(
+                state_at_event
+                    .into_iter()
+                    .map(|(_, pdu)| (pdu.event_id().clone(), pdu)),
+            );
+
             match state_res::StateResolution::resolve(
                 &pdu.room_id,
                 &RoomVersionId::Version6,
@@ -784,7 +745,7 @@ pub async fn send_transaction_message_route<'a>(
                             .collect::<StateMap<_>>()
                     })
                     .collect::<Vec<_>>(),
-                None,
+                &mut event_map,
                 &db.rooms,
             ) {
                 Ok(res) => res
@@ -819,8 +780,74 @@ pub async fn send_transaction_message_route<'a>(
     Ok(send_transaction_message::v1::Response { pdus: resolved_map }.into())
 }
 
+fn signature_and_hash_check(
+    pub_key_map: &ruma::signatures::PublicKeyMap,
+    value: CanonicalJsonObject,
+) -> std::result::Result<PduEvent, String> {
+    let val = match ruma::signatures::verify_event(pub_key_map, &value, &RoomVersionId::Version6) {
+        Ok(ver) => {
+            if let ruma::signatures::Verified::Signatures = ver {
+                match ruma::signatures::redact(&value, &RoomVersionId::Version6) {
+                    Ok(obj) => obj,
+                    Err(_) => return Err("Redaction failed".into()),
+                }
+            } else {
+                value
+            }
+        }
+        Err(_e) => return Err("Signature verification failed".into()),
+    };
+
+    serde_json::from_value::<PduEvent>(
+        serde_json::to_value(val).expect("CanonicalJsonObj is a valid JsonValue"),
+    )
+    .map_err(|_| "Deserialization failed for JSON value".into())
+}
+
+/// TODO: this needs to add events to the DB in a way that does not
+/// effect the state of the room
+async fn fetch_events(
+    db: &Database,
+    origin: Box<ServerName>,
+    key_map: &PublicKeyMap,
+    events: &[EventId],
+) -> Result<Vec<PduEvent>> {
+    let mut pdus = vec![];
+    for id in events {
+        match db.rooms.get_pdu(id)? {
+            Some(pdu) => pdus.push(pdu),
+            None => match db
+                .sending
+                .send_federation_request(
+                    &db.globals,
+                    origin.clone(),
+                    get_event::v1::Request { event_id: id },
+                )
+                .await
+            {
+                Ok(res) => {
+                    let (_, value) = crate::pdu::process_incoming_pdu(&res.pdu);
+                    match signature_and_hash_check(key_map, value) {
+                        Ok(pdu) => {
+                            // TODO: add to our DB somehow?
+                            pdus.push(pdu);
+                        }
+                        Err(e) => {
+                            // TODO: I would assume we just keep going
+                            error!("{:?}", e);
+                            continue;
+                        }
+                    }
+                }
+                Err(_) => return Err(Error::BadServerResponse("Failed to fetch event")),
+            },
+        }
+    }
+    Ok(pdus)
+}
+
 fn forward_extremity_ids(db: &Database, room_id: &RoomId) -> Result<Vec<EventId>> {
-    todo!()
+    db.rooms.get_pdu_leaves(room_id)
 }
 
 fn append_state(db: &Database, pdu: &PduEvent) -> Result<()> {
@@ -854,20 +881,15 @@ fn append_state_soft(db: &Database, pdu: &PduEvent) -> Result<()> {
     pdu_id.push(0xff);
     pdu_id.extend_from_slice(&count.to_be_bytes());
 
-    db.rooms.append_to_state(&pdu_id, pdu, &db.globals)?;
-    db.rooms.append_pdu(
-        pdu,
-        &utils::to_canonical_object(pdu).expect("Pdu is valid canonical object"),
-        count,
-        pdu_id.clone().into(),
-        &db.globals,
-        &db.account_data,
-        &db.admin,
-    )?;
-
-    for appservice in db.appservice.iter_all().filter_map(|r| r.ok()) {
-        db.sending.send_pdu_appservice(&appservice.0, &pdu_id)?;
-    }
+    // db.rooms.append_pdu(
+    //     pdu,
+    //     &utils::to_canonical_object(pdu).expect("Pdu is valid canonical object"),
+    //     count,
+    //     pdu_id.clone().into(),
+    //     &db.globals,
+    //     &db.account_data,
+    //     &db.admin,
+    // )?;
 
     Ok(())
 }