Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
conduwuit
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
🥺
conduwuit
Commits
48601142
Commit
48601142
authored
4 years ago
by
Devin Ragotzy
Browse files
Options
Downloads
Patches
Plain Diff
Use auth_cache to avoid db, save state for every event when joining
parent
74d530ae
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
src/client_server/membership.rs
+4
-10
4 additions, 10 deletions
src/client_server/membership.rs
src/database.rs
+1
-0
1 addition, 0 deletions
src/database.rs
src/database/rooms.rs
+54
-1
54 additions, 1 deletion
src/database/rooms.rs
src/server_server.rs
+32
-23
32 additions, 23 deletions
src/server_server.rs
with
91 additions
and
34 deletions
src/client_server/membership.rs
+
4
−
10
View file @
48601142
...
@@ -643,8 +643,6 @@ async fn join_room_by_id_helper(
...
@@ -643,8 +643,6 @@ async fn join_room_by_id_helper(
)
)
.expect
(
"iterative auth check failed on resolved events"
);
.expect
(
"iterative auth check failed on resolved events"
);
let
mut
state
=
HashMap
::
new
();
// filter the events that failed the auth check keeping the remaining events
// filter the events that failed the auth check keeping the remaining events
// sorted correctly
// sorted correctly
for
ev_id
in
sorted_event_ids
for
ev_id
in
sorted_event_ids
...
@@ -660,24 +658,20 @@ async fn join_room_by_id_helper(
...
@@ -660,24 +658,20 @@ async fn join_room_by_id_helper(
let
mut
pdu_id
=
room_id
.as_bytes
()
.to_vec
();
let
mut
pdu_id
=
room_id
.as_bytes
()
.to_vec
();
pdu_id
.push
(
0xff
);
pdu_id
.push
(
0xff
);
pdu_id
.extend_from_slice
(
&
count
.to_be_bytes
());
pdu_id
.extend_from_slice
(
&
count
.to_be_bytes
());
let
hash
=
db
.rooms
.append_to_state
(
&
pdu_id
,
&
pdu
,
&
db
.globals
)
?
;
db
.rooms
.append_pdu
(
db
.rooms
.append_pdu
(
&
pdu
,
&
pdu
,
utils
::
to_canonical_object
(
&**
pdu
)
.expect
(
"Pdu is valid canonical object"
),
utils
::
to_canonical_object
(
&**
pdu
)
.expect
(
"Pdu is valid canonical object"
),
count
,
count
,
pdu_id
.clone
()
.into
(),
pdu_id
.clone
()
.into
(),
// TODO: can we simplify the DAG or should we copy it exactly??
&
pdu
.prev_events
,
&
pdu
.prev_events
,
&
db
,
&
db
,
)
?
;
)
?
;
if
state_events
.contains
(
ev_id
)
{
db
.rooms
.set_room_state
(
room_id
,
&
hash
)
?
;
if
let
Some
(
key
)
=
&
pdu
.state_key
{
state
.insert
((
pdu
.kind
(),
key
.to_string
()),
pdu_id
);
}
}
}
}
db
.rooms
.force_state
(
room_id
,
state
,
&
db
.globals
)
?
;
}
else
{
}
else
{
let
event
=
member
::
MemberEventContent
{
let
event
=
member
::
MemberEventContent
{
membership
:
member
::
MembershipState
::
Join
,
membership
:
member
::
MembershipState
::
Join
,
...
...
This diff is collapsed.
Click to expand it.
src/database.rs
+
1
−
0
View file @
48601142
...
@@ -161,6 +161,7 @@ pub async fn load_or_create(config: Config) -> Result<Self> {
...
@@ -161,6 +161,7 @@ pub async fn load_or_create(config: Config) -> Result<Self> {
roomid_statehash
:
db
.open_tree
(
"roomid_statehash"
)
?
,
roomid_statehash
:
db
.open_tree
(
"roomid_statehash"
)
?
,
roomeventid_outlierpdu
:
db
.open_tree
(
"roomeventid_outlierpdu"
)
?
,
roomeventid_outlierpdu
:
db
.open_tree
(
"roomeventid_outlierpdu"
)
?
,
prevevent_parent
:
db
.open_tree
(
"prevevent_parent"
)
?
,
prevevent_parent
:
db
.open_tree
(
"prevevent_parent"
)
?
,
roomeventid_outlierpducount
:
db
.open_tree
(
"roomeventid_outlierpducount"
)
?
,
},
},
account_data
:
account_data
::
AccountData
{
account_data
:
account_data
::
AccountData
{
roomuserdataid_accountdata
:
db
.open_tree
(
"roomuserdataid_accountdata"
)
?
,
roomuserdataid_accountdata
:
db
.open_tree
(
"roomuserdataid_accountdata"
)
?
,
...
...
This diff is collapsed.
Click to expand it.
src/database/rooms.rs
+
54
−
1
View file @
48601142
...
@@ -69,6 +69,10 @@ pub struct Rooms {
...
@@ -69,6 +69,10 @@ pub struct Rooms {
/// RoomId + EventId -> outlier PDU.
/// RoomId + EventId -> outlier PDU.
/// Any pdu that has passed the steps 1-8 in the incoming event /federation/send/txn.
/// Any pdu that has passed the steps 1-8 in the incoming event /federation/send/txn.
pub
(
super
)
roomeventid_outlierpdu
:
sled
::
Tree
,
pub
(
super
)
roomeventid_outlierpdu
:
sled
::
Tree
,
/// RoomId + EventId -> count of the last known pdu when the outlier was inserted.
/// This allows us to skip any state snapshots that would for sure not have the outlier.
pub
(
super
)
roomeventid_outlierpducount
:
sled
::
Tree
,
/// RoomId + EventId -> Parent PDU EventId.
/// RoomId + EventId -> Parent PDU EventId.
pub
(
super
)
prevevent_parent
:
sled
::
Tree
,
pub
(
super
)
prevevent_parent
:
sled
::
Tree
,
}
}
...
@@ -323,6 +327,15 @@ pub fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<u64>> {
...
@@ -323,6 +327,15 @@ pub fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<u64>> {
.map_or
(
Ok
(
None
),
|
pdu_id
|
self
.pdu_count
(
&
pdu_id
)
.map
(
Some
))
.map_or
(
Ok
(
None
),
|
pdu_id
|
self
.pdu_count
(
&
pdu_id
)
.map
(
Some
))
}
}
pub
fn
latest_pdu_count
(
&
self
,
room_id
:
&
RoomId
)
->
Result
<
u64
>
{
self
.pduid_pdu
.scan_prefix
(
room_id
.as_bytes
())
.last
()
.map
(|
b
|
self
.pdu_count
(
&
b
?
.0
))
.transpose
()
.map
(|
op
|
op
.unwrap_or_default
())
}
/// Returns the json of a pdu.
/// Returns the json of a pdu.
pub
fn
get_pdu_json
(
&
self
,
event_id
:
&
EventId
)
->
Result
<
Option
<
serde_json
::
Value
>>
{
pub
fn
get_pdu_json
(
&
self
,
event_id
:
&
EventId
)
->
Result
<
Option
<
serde_json
::
Value
>>
{
self
.eventid_pduid
self
.eventid_pduid
...
@@ -490,6 +503,8 @@ pub fn append_pdu_outlier(&self, pdu: &PduEvent) -> Result<()> {
...
@@ -490,6 +503,8 @@ pub fn append_pdu_outlier(&self, pdu: &PduEvent) -> Result<()> {
&
key
,
&
key
,
&*
serde_json
::
to_string
(
&
pdu
)
.expect
(
"PduEvent is always a valid String"
),
&*
serde_json
::
to_string
(
&
pdu
)
.expect
(
"PduEvent is always a valid String"
),
)
?
;
)
?
;
self
.roomeventid_outlierpducount
.insert
(
&
key
,
&
self
.latest_pdu_count
(
pdu
.room_id
())
?
.to_be_bytes
())
?
;
Ok
(())
Ok
(())
}
}
...
@@ -537,7 +552,45 @@ pub fn append_pdu(
...
@@ -537,7 +552,45 @@ pub fn append_pdu(
let
mut
key
=
pdu
.room_id
()
.as_bytes
()
.to_vec
();
let
mut
key
=
pdu
.room_id
()
.as_bytes
()
.to_vec
();
key
.push
(
0xff
);
key
.push
(
0xff
);
key
.extend_from_slice
(
pdu
.event_id
()
.as_bytes
());
key
.extend_from_slice
(
pdu
.event_id
()
.as_bytes
());
self
.roomeventid_outlierpdu
.remove
(
key
)
?
;
if
self
.roomeventid_outlierpdu
.remove
(
&
key
)
?
.is_some
()
{
if
let
Some
(
state_key
)
=
pdu
.state_key
.as_deref
()
{
let
mut
statekey
=
pdu
.kind
()
.as_ref
()
.as_bytes
()
.to_vec
();
statekey
.extend_from_slice
(
state_key
.as_bytes
());
let
short
=
match
self
.statekey_short
.get
(
&
statekey
)
?
{
Some
(
short
)
=>
utils
::
u64_from_bytes
(
&
short
)
.map_err
(|
_
|
{
Error
::
bad_database
(
"Invalid short bytes in statekey_short."
)
})
?
,
None
=>
{
error!
(
"This event has been inserted into the state snapshot tree previously."
);
let
short
=
db
.globals
.next_count
()
?
;
self
.statekey_short
.insert
(
&
statekey
,
&
short
.to_be_bytes
())
?
;
short
}
};
let
mut
start
=
pdu
.room_id
()
.as_bytes
()
.to_vec
();
start
.extend_from_slice
(
&
self
.roomeventid_outlierpducount
.get
(
&
key
)
?
.unwrap_or_default
(),
);
for
hash
in
self
.pduid_statehash
.range
(
start
..
)
.values
()
{
let
mut
hash
=
hash
?
.to_vec
();
hash
.extend_from_slice
(
&
short
.to_be_bytes
());
let
_
=
self
.stateid_pduid
.compare_and_swap
(
hash
,
Some
(
pdu
.event_id
()
.as_bytes
()),
Some
(
pdu_id
.as_ref
()),
)
?
;
}
}
}
// We must keep track of all events that have been referenced.
// We must keep track of all events that have been referenced.
for
leaf
in
leaves
{
for
leaf
in
leaves
{
...
...
This diff is collapsed.
Click to expand it.
src/server_server.rs
+
32
−
23
View file @
48601142
...
@@ -971,6 +971,7 @@ fn validate_event<'a>(
...
@@ -971,6 +971,7 @@ fn validate_event<'a>(
}
}
}
}
Err
(
_e
)
=>
{
Err
(
_e
)
=>
{
error!
(
"{}"
,
_e
);
return
Err
(
"Signature verification failed"
.to_string
());
return
Err
(
"Signature verification failed"
.to_string
());
}
}
};
};
...
@@ -988,7 +989,7 @@ fn validate_event<'a>(
...
@@ -988,7 +989,7 @@ fn validate_event<'a>(
fetch_check_auth_events
(
db
,
origin
,
pub_key_map
,
&
pdu
.auth_events
,
auth_cache
)
fetch_check_auth_events
(
db
,
origin
,
pub_key_map
,
&
pdu
.auth_events
,
auth_cache
)
.await
.await
.map_err
(|
_
|
"Event failed auth chain check"
.to_string
())
?
;
.map_err
(|
e
|
e
.to_string
())
?
;
let
pdu
=
Arc
::
new
(
pdu
.clone
());
let
pdu
=
Arc
::
new
(
pdu
.clone
());
...
@@ -1064,6 +1065,7 @@ async fn fetch_check_auth_events(
...
@@ -1064,6 +1065,7 @@ async fn fetch_check_auth_events(
/// Find the event and auth it. Once the event is validated (steps 1 - 8)
/// Find the event and auth it. Once the event is validated (steps 1 - 8)
/// it is appended to the outliers Tree.
/// it is appended to the outliers Tree.
///
///
/// 0. Look in the auth_cache
/// 1. Look in the main timeline (pduid_pdu tree)
/// 1. Look in the main timeline (pduid_pdu tree)
/// 2. Look at outlier pdu tree
/// 2. Look at outlier pdu tree
/// 3. Ask origin server over federation
/// 3. Ask origin server over federation
...
@@ -1080,28 +1082,35 @@ pub(crate) async fn fetch_events(
...
@@ -1080,28 +1082,35 @@ pub(crate) async fn fetch_events(
)
->
Result
<
Vec
<
Arc
<
PduEvent
>>>
{
)
->
Result
<
Vec
<
Arc
<
PduEvent
>>>
{
let
mut
pdus
=
vec!
[];
let
mut
pdus
=
vec!
[];
for
id
in
events
{
for
id
in
events
{
// `get_pdu` checks the outliers tree for us
let
pdu
=
match
auth_cache
.get
(
id
)
{
let
pdu
=
match
db
.rooms
.get_pdu
(
&
id
)
?
{
Some
(
pdu
)
=>
pdu
.clone
(),
Some
(
pdu
)
=>
Arc
::
new
(
pdu
),
// `get_pdu` checks the outliers tree for us
None
=>
match
db
None
=>
match
db
.rooms
.get_pdu
(
&
id
)
?
{
.sending
Some
(
pdu
)
=>
Arc
::
new
(
pdu
),
.send_federation_request
(
None
=>
match
db
&
db
.globals
,
.sending
origin
,
.send_federation_request
(
get_event
::
v1
::
Request
{
event_id
:
&
id
},
&
db
.globals
,
)
origin
,
.await
get_event
::
v1
::
Request
{
event_id
:
&
id
},
{
)
Ok
(
res
)
=>
{
.await
let
(
event_id
,
value
)
=
crate
::
pdu
::
gen_event_id_canonical_json
(
&
res
.pdu
);
{
let
(
pdu
,
_
)
=
validate_event
(
db
,
value
,
event_id
,
key_map
,
origin
,
auth_cache
)
Ok
(
res
)
=>
{
.await
let
(
event_id
,
value
)
=
crate
::
pdu
::
gen_event_id_canonical_json
(
&
res
.pdu
);
.map_err
(|
_
|
Error
::
Conflict
(
"Authentication of event failed"
))
?
;
let
(
pdu
,
_
)
=
validate_event
(
db
,
value
,
event_id
,
key_map
,
origin
,
auth_cache
)
db
.rooms
.append_pdu_outlier
(
&
pdu
)
?
;
.await
pdu
.map_err
(|
e
|
{
}
error!
(
"{:?}"
,
e
);
Err
(
_
)
=>
return
Err
(
Error
::
BadServerResponse
(
"Failed to fetch event"
)),
Error
::
Conflict
(
"Authentication of event failed"
)
})
?
;
db
.rooms
.append_pdu_outlier
(
&
pdu
)
?
;
pdu
}
Err
(
_
)
=>
return
Err
(
Error
::
BadServerResponse
(
"Failed to fetch event"
)),
},
},
},
};
};
auth_cache
.entry
(
id
.clone
())
.or_insert_with
(||
pdu
.clone
());
auth_cache
.entry
(
id
.clone
())
.or_insert_with
(||
pdu
.clone
());
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment