|
|
|
@ -569,7 +569,7 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
// discard the event whereas the Client Server API's /send/{eventType} endpoint
|
|
|
|
// discard the event whereas the Client Server API's /send/{eventType} endpoint
|
|
|
|
// would return a M_BAD_JSON error.
|
|
|
|
// would return a M_BAD_JSON error.
|
|
|
|
let mut resolved_map = BTreeMap::new(); |
|
|
|
let mut resolved_map = BTreeMap::new(); |
|
|
|
for pdu in &body.pdus { |
|
|
|
'main_pdu_loop: for pdu in &body.pdus { |
|
|
|
// 1. Is a valid event, otherwise it is dropped.
|
|
|
|
// 1. Is a valid event, otherwise it is dropped.
|
|
|
|
// Ruma/PduEvent/StateEvent satisfies this
|
|
|
|
// Ruma/PduEvent/StateEvent satisfies this
|
|
|
|
// We do not add the event_id field to the pdu here because of signature and hashes checks
|
|
|
|
// We do not add the event_id field to the pdu here because of signature and hashes checks
|
|
|
|
@ -660,7 +660,6 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
let pdu = Arc::new(pdu.clone()); |
|
|
|
let pdu = Arc::new(pdu.clone()); |
|
|
|
|
|
|
|
|
|
|
|
// Fetch any unknown prev_events or retrieve them from the DB
|
|
|
|
// Fetch any unknown prev_events or retrieve them from the DB
|
|
|
|
let previous = match fetch_events( |
|
|
|
let previous = match fetch_events( |
|
|
|
&db, |
|
|
|
&db, |
|
|
|
@ -675,6 +674,7 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
_ => None, |
|
|
|
_ => None, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// [auth_cache] At this point we have the auth chain of the incoming event.
|
|
|
|
let mut event_map: state_res::EventMap<Arc<PduEvent>> = auth_cache |
|
|
|
let mut event_map: state_res::EventMap<Arc<PduEvent>> = auth_cache |
|
|
|
.iter() |
|
|
|
.iter() |
|
|
|
.map(|(k, v)| (k.clone(), v.clone())) |
|
|
|
.map(|(k, v)| (k.clone(), v.clone())) |
|
|
|
@ -688,7 +688,7 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
&pdu.auth_events |
|
|
|
&pdu.auth_events |
|
|
|
.iter() |
|
|
|
.iter() |
|
|
|
.map(|id| { |
|
|
|
.map(|id| { |
|
|
|
event_map |
|
|
|
auth_cache |
|
|
|
.get(id) |
|
|
|
.get(id) |
|
|
|
.map(|pdu| ((pdu.kind(), pdu.state_key()), pdu.clone())) |
|
|
|
.map(|pdu| ((pdu.kind(), pdu.state_key()), pdu.clone())) |
|
|
|
.ok_or_else(|| { |
|
|
|
.ok_or_else(|| { |
|
|
|
@ -790,7 +790,15 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
// End of step 5.
|
|
|
|
// End of step 5.
|
|
|
|
|
|
|
|
|
|
|
|
// Gather the forward extremities and resolve
|
|
|
|
// Gather the forward extremities and resolve
|
|
|
|
let fork_states = match forward_extremity_ids(&db, &pdu) { |
|
|
|
let fork_states = match forward_extremity_ids( |
|
|
|
|
|
|
|
&db, |
|
|
|
|
|
|
|
&pdu, |
|
|
|
|
|
|
|
server_name, |
|
|
|
|
|
|
|
&pub_key_map, |
|
|
|
|
|
|
|
&mut auth_cache, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
.await |
|
|
|
|
|
|
|
{ |
|
|
|
Ok(states) => states, |
|
|
|
Ok(states) => states, |
|
|
|
Err(_) => { |
|
|
|
Err(_) => { |
|
|
|
resolved_map.insert(event_id, Err("Failed to gather forward extremities".into())); |
|
|
|
resolved_map.insert(event_id, Err("Failed to gather forward extremities".into())); |
|
|
|
@ -805,47 +813,44 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
} else if fork_states.len() == 1 { |
|
|
|
} else if fork_states.len() == 1 { |
|
|
|
fork_states[0].clone() |
|
|
|
fork_states[0].clone() |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
|
|
|
|
// TODO: remove this is for current debugging Jan, 15 2021
|
|
|
|
|
|
|
|
let mut number_fetches = 0_u32; |
|
|
|
let mut auth_events = vec![]; |
|
|
|
let mut auth_events = vec![]; |
|
|
|
// this keeps track if we error so we can break out of these inner loops
|
|
|
|
// this keeps track if we error so we can break out of these inner loops
|
|
|
|
// to continue on with the incoming PDU's
|
|
|
|
// to continue on with the incoming PDU's
|
|
|
|
let mut failed = false; |
|
|
|
|
|
|
|
for map in &fork_states { |
|
|
|
for map in &fork_states { |
|
|
|
let mut state_auth = vec![]; |
|
|
|
let mut state_auth = vec![]; |
|
|
|
for pdu in map.values() { |
|
|
|
for auth_id in map.values().flat_map(|pdu| &pdu.auth_events) { |
|
|
|
let event = match auth_cache.get(pdu.event_id()) { |
|
|
|
let event = match auth_cache.get(auth_id) { |
|
|
|
Some(aev) => aev.clone(), |
|
|
|
Some(aev) => aev.clone(), |
|
|
|
// We should know about every event at this point but just incase...
|
|
|
|
// We should know about every event at this point but just incase...
|
|
|
|
None => match fetch_events( |
|
|
|
None => match fetch_events( |
|
|
|
&db, |
|
|
|
&db, |
|
|
|
server_name, |
|
|
|
server_name, |
|
|
|
&pub_key_map, |
|
|
|
&pub_key_map, |
|
|
|
&[pdu.event_id().clone()], |
|
|
|
&[auth_id.clone()], |
|
|
|
&mut auth_cache, |
|
|
|
&mut auth_cache, |
|
|
|
) |
|
|
|
) |
|
|
|
.await |
|
|
|
.await |
|
|
|
.map(|mut vec| vec.remove(0)) |
|
|
|
.map(|mut vec| { |
|
|
|
{ |
|
|
|
number_fetches += 1; |
|
|
|
Ok(aev) => aev.clone(), |
|
|
|
vec.remove(0) |
|
|
|
|
|
|
|
}) { |
|
|
|
|
|
|
|
Ok(aev) => aev, |
|
|
|
Err(_) => { |
|
|
|
Err(_) => { |
|
|
|
resolved_map.insert( |
|
|
|
resolved_map.insert( |
|
|
|
event_id.clone(), |
|
|
|
event_id.clone(), |
|
|
|
Err("Event has been soft failed".into()), |
|
|
|
Err("Event has been soft failed".into()), |
|
|
|
); |
|
|
|
); |
|
|
|
failed = true; |
|
|
|
continue 'main_pdu_loop; |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
}; |
|
|
|
}; |
|
|
|
state_auth.push(event); |
|
|
|
state_auth.push(event); |
|
|
|
} |
|
|
|
} |
|
|
|
if failed { |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
auth_events.push(state_auth); |
|
|
|
auth_events.push(state_auth); |
|
|
|
} |
|
|
|
} |
|
|
|
if failed { |
|
|
|
info!("{} event's were not in the auth_cache", number_fetches); |
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add everything we will need to event_map
|
|
|
|
// Add everything we will need to event_map
|
|
|
|
event_map.extend( |
|
|
|
event_map.extend( |
|
|
|
@ -886,7 +891,13 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
.into_iter() |
|
|
|
.into_iter() |
|
|
|
.map(|(k, v)| (k, Arc::new(db.rooms.get_pdu(&v).unwrap().unwrap()))) |
|
|
|
.map(|(k, v)| (k, Arc::new(db.rooms.get_pdu(&v).unwrap().unwrap()))) |
|
|
|
.collect(), |
|
|
|
.collect(), |
|
|
|
Err(e) => panic!("{:?}", e), |
|
|
|
Err(_) => { |
|
|
|
|
|
|
|
resolved_map.insert( |
|
|
|
|
|
|
|
pdu.event_id().clone(), |
|
|
|
|
|
|
|
Err("State resolution failed, either an event could not be found or deserialization".into()), |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
continue 'main_pdu_loop; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
@ -914,6 +925,7 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
Ok(dbg!(send_transaction_message::v1::Response { pdus: resolved_map }).into()) |
|
|
|
Ok(dbg!(send_transaction_message::v1::Response { pdus: resolved_map }).into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// TODO: don't add as outlier if event is fetched as a result of gathering auth_events
|
|
|
|
/// Validate any event that is given to us by another server.
|
|
|
|
/// Validate any event that is given to us by another server.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// 1. Is a valid event, otherwise it is dropped (PduEvent deserialization satisfies this).
|
|
|
|
/// 1. Is a valid event, otherwise it is dropped (PduEvent deserialization satisfies this).
|
|
|
|
@ -955,6 +967,37 @@ fn validate_event<'a>( |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// TODO: don't add as outlier if event is fetched as a result of gathering auth_events
|
|
|
|
|
|
|
|
/// The check in `fetch_check_auth_events` is that a complete chain is found for the
|
|
|
|
|
|
|
|
/// events `auth_events`. If the chain is found to have any missing events it fails.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// The `auth_cache` is filled instead of returning a `Vec`.
|
|
|
|
|
|
|
|
async fn fetch_check_auth_events( |
|
|
|
|
|
|
|
db: &Database, |
|
|
|
|
|
|
|
origin: &ServerName, |
|
|
|
|
|
|
|
key_map: &PublicKeyMap, |
|
|
|
|
|
|
|
event_ids: &[EventId], |
|
|
|
|
|
|
|
auth_cache: &mut EventMap<Arc<PduEvent>>, |
|
|
|
|
|
|
|
) -> Result<()> { |
|
|
|
|
|
|
|
let mut stack = event_ids.to_vec(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DFS for auth event chain
|
|
|
|
|
|
|
|
while !stack.is_empty() { |
|
|
|
|
|
|
|
let ev_id = stack.pop().unwrap(); |
|
|
|
|
|
|
|
if auth_cache.contains_key(&ev_id) { |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let ev = fetch_events(db, origin, key_map, &[ev_id.clone()], auth_cache) |
|
|
|
|
|
|
|
.await |
|
|
|
|
|
|
|
.map(|mut vec| vec.remove(0))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stack.extend(ev.auth_events()); |
|
|
|
|
|
|
|
auth_cache.insert(ev.event_id().clone(), ev); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Find the event and auth it.
|
|
|
|
/// Find the event and auth it.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// 1. Look in the main timeline (pduid_pdu tree)
|
|
|
|
/// 1. Look in the main timeline (pduid_pdu tree)
|
|
|
|
@ -1000,36 +1043,6 @@ async fn fetch_events( |
|
|
|
Ok(pdus) |
|
|
|
Ok(pdus) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// The check in `fetch_check_auth_events` is that a complete chain is found for the
|
|
|
|
|
|
|
|
/// events `auth_events`. If the chain is found to have any missing events it fails.
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
/// The `auth_cache` is filled instead of returning a `Vec`.
|
|
|
|
|
|
|
|
async fn fetch_check_auth_events( |
|
|
|
|
|
|
|
db: &Database, |
|
|
|
|
|
|
|
origin: &ServerName, |
|
|
|
|
|
|
|
key_map: &PublicKeyMap, |
|
|
|
|
|
|
|
event_ids: &[EventId], |
|
|
|
|
|
|
|
auth_cache: &mut EventMap<Arc<PduEvent>>, |
|
|
|
|
|
|
|
) -> Result<()> { |
|
|
|
|
|
|
|
let mut stack = event_ids.to_vec(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DFS for auth event chain
|
|
|
|
|
|
|
|
while !stack.is_empty() { |
|
|
|
|
|
|
|
let ev_id = stack.pop().unwrap(); |
|
|
|
|
|
|
|
if auth_cache.contains_key(&ev_id) { |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let ev = fetch_events(db, origin, key_map, &[ev_id.clone()], auth_cache) |
|
|
|
|
|
|
|
.await |
|
|
|
|
|
|
|
.map(|mut vec| vec.remove(0))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stack.extend(ev.auth_events()); |
|
|
|
|
|
|
|
auth_cache.insert(ev.event_id().clone(), ev); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Search the DB for the signing keys of the given server, if we don't have them
|
|
|
|
/// Search the DB for the signing keys of the given server, if we don't have them
|
|
|
|
/// fetch them from the server and save to our DB.
|
|
|
|
/// fetch them from the server and save to our DB.
|
|
|
|
async fn fetch_signing_keys( |
|
|
|
async fn fetch_signing_keys( |
|
|
|
@ -1049,6 +1062,7 @@ async fn fetch_signing_keys( |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn signature_and_hash_check( |
|
|
|
fn signature_and_hash_check( |
|
|
|
pub_key_map: &ruma::signatures::PublicKeyMap, |
|
|
|
pub_key_map: &ruma::signatures::PublicKeyMap, |
|
|
|
value: CanonicalJsonObject, |
|
|
|
value: CanonicalJsonObject, |
|
|
|
@ -1073,9 +1087,23 @@ fn signature_and_hash_check( |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn forward_extremity_ids(db: &Database, pdu: &PduEvent) -> Result<Vec<StateMap<Arc<PduEvent>>>> { |
|
|
|
async fn forward_extremity_ids( |
|
|
|
|
|
|
|
db: &Database, |
|
|
|
|
|
|
|
pdu: &PduEvent, |
|
|
|
|
|
|
|
origin: &ServerName, |
|
|
|
|
|
|
|
pub_key_map: &PublicKeyMap, |
|
|
|
|
|
|
|
auth_cache: &mut EventMap<Arc<PduEvent>>, |
|
|
|
|
|
|
|
) -> Result<Vec<StateMap<Arc<PduEvent>>>> { |
|
|
|
|
|
|
|
let mut current_leaves = db.rooms.get_pdu_leaves(pdu.room_id())?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for incoming_leaf in &pdu.prev_events { |
|
|
|
|
|
|
|
if !current_leaves.contains(incoming_leaf) { |
|
|
|
|
|
|
|
current_leaves.push(incoming_leaf.clone()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let mut fork_states = vec![]; |
|
|
|
let mut fork_states = vec![]; |
|
|
|
for id in &db.rooms.get_pdu_leaves(pdu.room_id())? { |
|
|
|
for id in ¤t_leaves { |
|
|
|
if let Some(id) = db.rooms.get_pdu_id(id)? { |
|
|
|
if let Some(id) = db.rooms.get_pdu_id(id)? { |
|
|
|
let state_hash = db |
|
|
|
let state_hash = db |
|
|
|
.rooms |
|
|
|
.rooms |
|
|
|
@ -1090,11 +1118,32 @@ fn forward_extremity_ids(db: &Database, pdu: &PduEvent) -> Result<Vec<StateMap<A |
|
|
|
|
|
|
|
|
|
|
|
fork_states.push(state); |
|
|
|
fork_states.push(state); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return Err(Error::Conflict( |
|
|
|
let res = db |
|
|
|
"we don't know of a pdu that is part of our known forks OOPS", |
|
|
|
.sending |
|
|
|
)); |
|
|
|
.send_federation_request( |
|
|
|
|
|
|
|
&db.globals, |
|
|
|
|
|
|
|
origin, |
|
|
|
|
|
|
|
get_room_state_ids::v1::Request { |
|
|
|
|
|
|
|
room_id: pdu.room_id(), |
|
|
|
|
|
|
|
event_id: id, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
.await?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: This only adds events to the auth_cache, there is for sure a better way to
|
|
|
|
|
|
|
|
// do this...
|
|
|
|
|
|
|
|
fetch_events(&db, origin, &pub_key_map, &res.auth_chain_ids, auth_cache).await?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let state = fetch_events(&db, origin, &pub_key_map, &res.pdu_ids, auth_cache) |
|
|
|
|
|
|
|
.await? |
|
|
|
|
|
|
|
.into_iter() |
|
|
|
|
|
|
|
.map(|pdu| ((pdu.kind.clone(), pdu.state_key.clone()), pdu)) |
|
|
|
|
|
|
|
.collect(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fork_states.push(state); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Ok(fork_states) |
|
|
|
Ok(fork_states) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|