feat: Support acting as a notary server #2314

Open
nex wants to merge 25 commits from nex/feat/notary-server into main
Owner

This PR implements POST /_matrix/key/v2/query and GET /_matrix/key/v2/query/{server_name}, allowing continuwuity to act as a key notary server, and finally a trusted server..

Closes: #784, #1208

Pull request checklist:

  • This pull request targets the main branch, and the branch is named something other than
    main.
  • I have written an appropriate pull request title and my description is clear.
  • I understand I am responsible for the contents of this pull request.
  • I have followed the contributing guidelines:
This PR implements [`POST /_matrix/key/v2/query`](https://spec.matrix.org/v1.19/server-server-api/#post_matrixkeyv2query) and [`GET /_matrix/key/v2/query/{server_name}`](https://spec.matrix.org/v1.19/server-server-api/#get_matrixkeyv2queryservername), allowing continuwuity to act as a key notary server, and finally a trusted server.. <!-- Example: This pull request allows us to warp through time and space ten times faster than before by double-inverting the warp drive with hyperheated jump fluid, both making the drive faster and more efficient. This resolves the common issue where we have to wait more than 10 milliseconds to engage, use, and disengage the warp drive when travelling between galaxies. --> Closes: #784, #1208 <!-- Uncomment the above line(s) if your pull request fixes an issue or closes another pull request by superseding it. Replace `#...` with the issue/pr number, such as `#123`. --> **Pull request checklist:** <!-- You need to complete these before your PR can be considered. If you aren't sure about some, feel free to ask for clarification in #dev:continuwuity.org. --> - [x] This pull request targets the `main` branch, and the branch is named something other than `main`. - [x] I have written an appropriate pull request title and my description is clear. - [x] I understand I am responsible for the contents of this pull request. - I have followed the [contributing guidelines][c1]: - [x] My contribution follows the [code style][c2], if applicable. - [x] I ran [pre-commit checks][c1pc] before opening/drafting this pull request. - [x] I have [tested my contribution][c1t] (or proof-read it for documentation-only changes) myself, if applicable. This includes ensuring code compiles. - [x] My commit messages follow the [commit message format][c1cm] and are descriptive. <!-- Notes on these requirements: - While not required, we encourage you to sign your commits with GPG or SSH to attest the authenticity of your changes. - While we allow LLM-assisted contributions, we do not appreciate contributions that are low quality, which is typical of machine-generated contributions that have not had a lot of love and care from a human. Please do not open a PR if all you have done is asked ChatGPT to tidy up the codebase with a +-100,000 diff. - In the case of code style violations, reviewers may leave review comments/change requests indicating what the ideal change would look like. For example, a reviewer may suggest you lower a log level, or use `match` instead of `if/else` etc. - In the case of code style violations, pre-commit check failures, minor things like typos/spelling errors, and in some cases commit format violations, reviewers may modify your branch directly, typically by making changes and adding a commit. Particularly in the latter case, a reviewer may rebase your commits to squash "spammy" ones (like "fix", "fix", "actually fix"), and reword commit messages that don't satisfy the format. - Pull requests MUST pass the `Checks` CI workflows to be capable of being merged. This can only be bypassed in exceptional circumstances. If your CI flakes, let us know in matrix:r/dev:continuwuity.org. - Pull requests have to be based on the latest `main` commit before being merged. If the main branch changes while you're making your changes, you should make sure you rebase on main before opening a PR. Your branch will be rebased on main before it is merged if it has fallen behind. - We typically only do fast-forward merges, so your entire commit log will be included. Once in main, it's difficult to get out cleanly, so put on your best dress, smile for the cameras! --> [c1]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md [c2]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/docs/development/code_style.mdx [c1pc]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md#pre-commit-checks [c1t]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md#running-tests-locally [c1cm]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md#commit-messages
nex self-assigned this 2026-10-02 20:54:41 +00:00
feat: Strip extraneous signatures to avoid leaking our own notaries
Some checks failed
Auto Labeler / Apply labels based on changed files (pull_request_target) Successful in 4s
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Failing after 8s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m5s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m9s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 9m56s
dcf61d6487
ginger requested changes 2026-10-02 21:02:06 +00:00
Dismissed
@ -90,0 +103,4 @@
State(services): State<crate::State>,
body: Ruma<get_remote_server_keys_batch::v2::Request>,
) -> Result<get_remote_server_keys_batch::v2::Response> {
let total_queried_keys = body
Owner

you're gonna lose your mind when you learn about BTreeMap::len()

you're gonna lose your mind when you learn about `BTreeMap::len()`
Author
Owner

Yeah I will because you made me realise I'm calculating bullshit lmao. It's supposed to sum the length of each value map but instead it's just counting the length of the top level map. I can't believe I reimplemented len()

Yeah I will because you made me realise I'm calculating bullshit lmao. It's supposed to sum the length of each value map but instead it's just counting the length of the top level map. I can't believe I reimplemented len()
nex marked this conversation as resolved
@ -90,0 +119,4 @@
let mut response = Vec::with_capacity(total_queried_keys);
for (server_name, queries) in &body.server_keys {
if queries.is_empty() {
Owner

there is a fair bit of logic duplicated between this if and the code after it

there is a fair bit of logic duplicated between this `if` and the code after it
nex marked this conversation as resolved
@ -90,0 +151,4 @@
else {
continue;
};
if ssk.valid_until_ts < minimum_valid_until_ts || ssk.valid_until_ts > in_one_week() {
Owner

you might as well fix !2312 while you're at it (maybe by having in_one_week() be "in one week and one hour")

you might as well fix !2312 while you're at it (maybe by having `in_one_week()` be "in one week and one hour")
Author
Owner

Didn't see that issue, that's actually deliberate because otherwise the range check will always return true if someone returns keys that last forever, which defeats the purpose of the 7-day limit

Didn't see that issue, that's actually deliberate because otherwise the range check will always return true if someone returns keys that last forever, which defeats the purpose of the 7-day limit
Owner

I'm not sure I follow your logic, why isn't that possible with the current seven-day limit as opposed to a seven-day-and-one-hour limit?

I'm not sure I follow your logic, why isn't that possible with the current seven-day limit as opposed to a seven-day-and-one-hour limit?
Author
Owner

If you query a key on 2026-01-01, and receive a response that expires at 2026-02-01, accepting that response will result in a cache hit against that response for every lookup until February. This means a request to the origin won't be made until Feb, meaning the origin can't revoke any keys that may have been maliciously injected, or leaked, etc. All that clamping would do is prevent someone then sending an event that was created on 2026-02-01, at 2026-01-02 (since the 1st of Feb is more than 7 days in the future as of the 2nd of Jan). Now imagine someone's web server was hacked and someone published a key response for a decade...

I don't know where this "plus one hour" is coming from, the spec very clearly states exactly 7 days

If you query a key on 2026-01-01, and receive a response that expires at 2026-02-01, accepting that response will result in a cache hit against that response for every lookup until February. This means a request to the origin won't be made until Feb, meaning the origin can't revoke any keys that may have been maliciously injected, or leaked, etc. All that clamping would do is prevent someone then sending an event that was created on 2026-02-01, at 2026-01-02 (since the 1st of Feb is more than 7 days in the future as of the 2nd of Jan). Now imagine someone's web server was hacked and someone published a key response for a decade... I don't know where this "plus one hour" is coming from, the spec very clearly states exactly 7 days
Owner

"plus one hour" allows for clock skew, basically. intentionally lightly imprecise definition of 7 days

"plus one hour" allows for clock skew, basically. intentionally lightly imprecise definition of 7 days
Author
Owner

But whose skew? That accounts for a +1 timezone offset, but there's more timezones with >+1. People should just have the right time?

But whose skew? That accounts for a +1 timezone offset, but there's more timezones with >+1. People should just have the right time?
Owner

A) the issue isn't timezones, that's not what clock skee is, but latency and clocks that are off by a second or two
B) that over-caching sounds like a bug to me, you can make it so that you only treat the key as valid for the clamped length and then recheck that it's still on the origin.

A) the issue isn't timezones, that's not what clock skee is, but latency and clocks that are off by a second or two B) that over-caching sounds like a bug to me, you can make it so that you only treat the key as valid for the clamped length and then recheck that it's still on the origin.
Author
Owner

I can, but I'm not going to. It's not over-caching, it's working as intended: if there's a locally stored key that is in-date and valid, use that. I don't see why you'd do anything less?

I can, but I'm not going to. It's not over-caching, it's working as intended: if there's a locally stored key that is in-date and valid, use that. I don't see why you'd do anything less?
Author
Owner

(discussion out-of-band decided this is out of scope for this PR but Jade wants to tackle 2312 herself, so the issue was re-opened and assigned)

(discussion out-of-band decided this is out of scope for this PR but Jade wants to tackle 2312 herself, so the issue was re-opened and assigned)
nex marked this conversation as resolved
Owner

also you need a news fragment :3

also you need a news fragment :3
style: Condense repeated code into a reusable function
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 5s
Checks / Changelog / Check changelog is added (pull_request_target) Failing after 8s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m14s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m13s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 7m30s
6d3d24169a
nex changed title from feat: Support acting as a notary server to WIP: feat: Support acting as a notary server 2026-10-03 01:47:24 +00:00
chore: Add newsfrag
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 9s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m10s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m41s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m19s
e712759419
chore: Rebuild example config
All checks were successful
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 6s
Checks / Prek / Check changed files (pull_request) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m2s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m53s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 9m32s
a6656c6c33
fix: Don't short circuit if all requested servers have no query criteria
All checks were successful
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 12s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m35s
Checks / Prek / Check changed files (pull_request) Successful in 9s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 2m6s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m27s
1543c31889
Also adds some traces
fix: Deduplicate signing key responses if we already satisfied them
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 8s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m13s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m14s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 4m10s
09a7fba83b
fix: Refuse to process >4096 servers and/or >8192 keys
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 6s
Checks / Prek / Check changed files (pull_request) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m3s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 2m2s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 6m4s
80dd7d5071
pending msc
Jade force-pushed nex/feat/notary-server from 80dd7d5071
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 6s
Checks / Prek / Check changed files (pull_request) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m3s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 2m2s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 6m4s
to 69b4d6ffa4
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 6s
Checks / Prek / Check changed files (pull_request) Successful in 8s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m6s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 1m51s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 4m32s
2026-10-04 22:28:59 +00:00
Compare
fix: Enforce specific notary limits per MSC4556
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 9s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m3s
Checks / Prek / Check changed files (pull_request) Successful in 14s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 1m15s
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
bf251d0cde
nex changed title from WIP: feat: Support acting as a notary server to feat: Support acting as a notary server 2026-10-04 22:35:59 +00:00
fix: Don't serve expired responses in the criterialess path
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Has been cancelled
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Checks / Prek / Check changed files (pull_request) Has been cancelled
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
dec881457a
chore: Update trusted_servers docs
Some checks failed
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Checks / Prek / Check changed files (pull_request) Has been cancelled
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Changelog / Check changelog is added (pull_request_target) Has been cancelled
912880fb6a
Jade force-pushed nex/feat/notary-server from 912880fb6a
Some checks failed
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Checks / Prek / Check changed files (pull_request) Has been cancelled
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Changelog / Check changelog is added (pull_request_target) Has been cancelled
to 8cb173ad08
All checks were successful
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m6s
Checks / Prek / Check changed files (pull_request) Successful in 36s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 2m0s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m18s
2026-10-04 23:29:06 +00:00
Compare
@ -90,0 +137,4 @@
// )));
}
if total_queried_keys > MAX_KEYS_PER_QUERY {
// We shouldn't really enforce this before MSC4456 either, but not doing
Owner

Typo (MSC4556)

Typo (MSC4556)
nex marked this conversation as resolved
@ -90,0 +203,4 @@
// First contact the origin (if we're allowed to)
if server_keys.notary_may_contact_origin(&remote) {
debug_info!("Asking remote directly for verify keys");
if let Ok(res) = server_keys.origin_request(remote.clone(), start).await
Owner

Same here, i don't think this persists the keys

Same here, i don't think this persists the keys
Owner

No check to avoid self-federation in these too I don't think

No check to avoid self-federation in these too I don't think
Author
Owner

That check is in the federation execute layer*

*or it should be, ginger told me a few hours ago that it's suspiciously absent now

That check is in the federation execute layer* \*or it should be, ginger told me a few hours ago that it's suspiciously absent now
nex marked this conversation as resolved
@ -90,0 +209,4 @@
let index = results.len();
results.push(ssk);
for key_id in res.verify_keys.keys().chain(res.old_verify_keys.keys()) {
if queries.is_empty()
Owner

This changes during iteration, so the condition may change and cause additional keys to be returned

This changes during iteration, so the condition may change and cause additional keys to be returned
nex marked this conversation as resolved
@ -90,0 +213,4 @@
|| queries
.get(key_id)
.and_then(|c| c.minimum_valid_until_ts)
.is_none_or(|m| res.valid_until_ts >= m)
Owner

Did you mean something like .and_then(|c| c.minimum_valid_until_ts.is_none_or(|m| res.valid_until_ts >= m))? Otherwise this will return keys that weren't queried for

Did you mean something like `.and_then(|c| c.minimum_valid_until_ts.is_none_or(|m| res.valid_until_ts >= m))`? Otherwise this will return keys that weren't queried for
Author
Owner

Uhh probably? I think clippy complained when I did that though 🤔

Uhh probably? I think clippy complained when I did that though 🤔
nex marked this conversation as resolved
@ -90,0 +322,4 @@
.notary_may_contact_origin(&body.server_name)
&& let Ok(response) = services
.server_keys
.origin_request(body.server_name.clone(), min_valid_ts)
Owner

This doesn't persist the keys, right? Might that be an issue?

This doesn't persist the keys, right? Might that be an issue?
Author
Owner

uhhh I guess storing the keys could be an optimisation, but it's not an issue otherwise afaik

uhhh I guess storing the keys could be an optimisation, but it's not an issue otherwise afaik
@ -90,0 +242,4 @@
}
})
.ready_for_each(|signed_ssk| {
let ssk = signed_ssk.deserialize().unwrap();
Owner

Can't you just yield the ssk in the broad_filter_map above in a tuple to avoid pointless work here?

Can't you just yield the ssk in the broad_filter_map above in a tuple to avoid pointless work here?
Author
Owner

I didn't want to because sign_ssk moves ssk, but I suppose deserializing is probably more expensive than cloning

I didn't want to because `sign_ssk` moves ssk, but I suppose deserializing is probably more expensive than cloning
nex marked this conversation as resolved
@ -90,0 +332,4 @@
services.globals.server_name(),
)
.await
.map(|r| Ok(get_remote_server_keys::v2::Response::new(vec![r])))?;
Owner

.map(|r| get_remote_server_keys::v2::Response::new(vec![r]))?

`.map(|r| get_remote_server_keys::v2::Response::new(vec![r]))`?
Author
Owner

Has to return a Result<get_remote_server_keys::v2::Response> so the wrap is necessary. I'll just rid of the map

Has to return a `Result<get_remote_server_keys::v2::Response>` so the wrap is necessary. I'll just rid of the map
Author
Owner

Hmm, actually that's visually worse

		return Ok(get_remote_server_keys::v2::Response::new(vec![
			sign_ssk(
				&services.server_keys,
				response,
				&body.server_name,
				services.globals.server_name(),
			)
			.await?,
		]));

I'll keep the current chain

Hmm, actually that's visually worse ```rs return Ok(get_remote_server_keys::v2::Response::new(vec![ sign_ssk( &services.server_keys, response, &body.server_name, services.globals.server_name(), ) .await?, ])); ``` I'll keep the current chain
@ -90,0 +271,4 @@
continue;
};
if ssk.valid_until_ts < minimum_valid_until_ts || ssk.valid_until_ts > in_one_week() {
Owner

do you need to check expired_ts too? (and in other checks)

do you need to check `expired_ts` too? (and in other checks)
nex marked this conversation as resolved
@ -29,6 +34,7 @@ pub struct Service {
verify_keys: VerifyKeys,
services: Services,
db: Data,
last_lookup: SyncRwLock<HashMap<OwnedServerName, Instant>>,
Owner

Woo! Unbounded growth! Not really a huge issue tho lol

Woo! Unbounded growth! Not really a huge issue tho lol
Author
Owner

Yeahh I'm not too sure how to get around that without a cleanup task (which just defines a time window for the unbounded growth). I think the map will hold small enough data that it won't really matter

Yeahh I'm not too sure how to get around that without a cleanup task (which just defines a time window for the unbounded growth). I think the map will hold small enough data that it won't really matter
nex marked this conversation as resolved
@ -101,3 +101,3 @@
};
let mut canonical_object = to_canonical_object(notary_signatures)?;
Self::strip_extraneous_signatures(&mut canonical_object, &server_keys.server_name, &[
strip_extraneous_signatures(&mut canonical_object, &server_keys.server_name, &[
Owner

This seems like dead code anyway

This seems like dead code anyway
Author
Owner

This is very much live code? what do you mean?

This is very much live code? what do you mean?
Owner

You're making and stripping a canonical object but then not using it for anything as far as I can read?

You're making and stripping a canonical object but then not using it for anything as far as I can read?
Author
Owner

Oh yeah, you're right, it was meant to be passed to to_canonical_json_string_for_signing below

Oh yeah, you're right, it was meant to be passed to `to_canonical_json_string_for_signing` below
nex marked this conversation as resolved
ginger approved these changes 2026-10-05 13:24:10 +00:00
Owner

look at jade's comments 👍she said most of the stuff I would've said

look at jade's comments 👍she said most of the stuff I would've said
@ -90,0 +119,4 @@
}
let total_queried_servers = body.server_keys.len();
let total_queried_keys = body
Owner

Hmm actually is this counting right? Might be overcounting

Hmm actually is this counting right? Might be overcounting
Author
Owner

Deliberately so, if a request is {"server_keys": {"servername.example": {}}}, we'll count zero total keys, but it's more likely that we'll end up fetching at least 1 key response, so I figured counting each server name in the total query count makes sense

Deliberately so, if a request is `{"server_keys": {"servername.example": {}}}`, we'll count zero total keys, but it's more likely that we'll end up fetching at least 1 key response, so I figured counting each server name in the total query count makes sense
nex force-pushed nex/feat/notary-server from 8cb173ad08
All checks were successful
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m6s
Checks / Prek / Check changed files (pull_request) Successful in 36s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 2m0s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m18s
to ad9ca737b2
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 6s
Checks / Prek / Check changed files (pull_request) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m20s
Update flake hashes / update-flake-hashes (pull_request) Successful in 1m30s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 2m1s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 9m42s
2026-10-07 10:49:05 +00:00
Compare
nex requested review from Jade 2026-10-08 21:54:19 +00:00
nex force-pushed nex/feat/notary-server from ad9ca737b2
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 6s
Checks / Prek / Check changed files (pull_request) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m20s
Update flake hashes / update-flake-hashes (pull_request) Successful in 1m30s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 2m1s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 9m42s
to adc0e5d3b8
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 11s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m36s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m52s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 7m59s
2026-10-09 17:21:57 +00:00
Compare
feat: Update MSC4456 implementation, new route
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 9s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m12s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m22s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 7m23s
58c5875013
Jade force-pushed nex/feat/notary-server from 58c5875013
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 9s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m12s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m22s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 7m23s
to 298113c0a6
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 6s
Checks / Prek / Check changed files (pull_request) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m8s
Update flake hashes / update-flake-hashes (pull_request) Successful in 1m20s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 20m55s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 40m59s
2026-10-14 09:35:53 +00:00
Compare
Jade left a comment

You have the wrong MSC in one of your commit messages I think. And tests are failing.

failures:

---- server_keys::verify::tests::verify_notary_response_checks_valid_notary_signature stdout ----

thread 'server_keys::verify::tests::verify_notary_response_checks_valid_notary_signature' (6147872) panicked at src/service/server_keys/verify.rs:244:10:
Server keys from notary are valid: No valid signature from starstruck.systems present on signing keys response
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    server_keys::verify::tests::verify_notary_response_checks_valid_notary_signature
You have the wrong MSC in one of your commit messages I think. And tests are failing. ``` failures: ---- server_keys::verify::tests::verify_notary_response_checks_valid_notary_signature stdout ---- thread 'server_keys::verify::tests::verify_notary_response_checks_valid_notary_signature' (6147872) panicked at src/service/server_keys/verify.rs:244:10: Server keys from notary are valid: No valid signature from starstruck.systems present on signing keys response note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failures: server_keys::verify::tests::verify_notary_response_checks_valid_notary_signature ```
@ -28,0 +59,4 @@
State(services): State<crate::State>,
body: Ruma<get_remote_server_keys_batch::v2::Request>,
) -> Result<get_remote_server_keys_batch::v2::Response> {
query_inner(&services, &body.server_keys, false)
Owner

false -> true?

`false` -> `true`?
Lines 102-105
@ -28,0 +99,7 @@
// Count how many keys are being requested.
// Each server incurs a cost of at least one, and then the count of each key
// being queried per-server.
let total_queried_servers = body.len();
let total_queried_keys = body
.values()
.fold(body.len(), |acc, q| acc.saturating_add(q.len()));
Owner

Maybe

let total_queried_keys = body
    .values()
    .fold(0_usize, |acc, q| acc.saturating_add(q.len().max(1)));

would be better? It'll be less of an overcount.

Maybe ``` let total_queried_keys = body .values() .fold(0_usize, |acc, q| acc.saturating_add(q.len().max(1))); ``` would be better? It'll be less of an overcount.
@ -28,0 +122,4 @@
total_queried_servers > MAX_SERVERS_PER_QUERY || total_queried_keys > MAX_KEYS_PER_QUERY;
debug_info!("Fetching {total_queried_keys} keys across {} servers", body.len());
let mut futs: FuturesUnordered<_> = FuturesUnordered::new();
Owner

Probably want something to limit concurrency here

Probably want something to limit concurrency here
@ -83,0 +273,4 @@
let minimum_valid_until_ts = criteria
.clone()
.minimum_valid_until_ts
.unwrap_or_else(|| MilliSecondsSinceUnixEpoch(uint!(0)));
Owner

Doesn't this mean that the default could provide expired keys? But spec wants current time by default.
Perhaps:

let minimum_valid_until_ts = criteria.minimum_valid_until_ts.unwrap_or(start);
Doesn't this mean that the default could provide expired keys? But spec wants current time by default. Perhaps: ``` let minimum_valid_until_ts = criteria.minimum_valid_until_ts.unwrap_or(start); ```
@ -0,0 +23,4 @@
rate_limited: true,
authentication: ServerSignatures,
history: {
unstable("org.continuwuity.msc4553") => "/_matrix/key/unstable/org.continuwuity.msc4556/query",
Owner

4556?

`4556`?
@ -196,0 +260,4 @@
// We need to verify that this response is still trusted based on
// the current configuration. It's possible we got this response
// from a notary who we no longer trust.
if resp.valid_until_ts > in_one_week() || resp.valid_until_ts < now {
Owner

Remind me to come back to this condition later.

Remind me to come back to this condition later.
@ -100,13 +100,12 @@ impl super::Service {
)));
};
let mut canonical_object = to_canonical_object(notary_signatures)?;
Owner

Did you mean
let mut canonical_object = to_canonical_object(server_keys)?;
(this is probably the cause of the test fail)

Did you mean `let mut canonical_object = to_canonical_object(server_keys)?;` (this is probably the cause of the test fail)
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 6s
Required
Details
Checks / Prek / Check changed files (pull_request) Successful in 7s
Required
Details
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m8s
Update flake hashes / update-flake-hashes (pull_request) Successful in 1m20s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 20m55s
Required
Details
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 40m59s
Required
Details
This pull request has changes requested by an official reviewer.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin nex/feat/notary-server:nex/feat/notary-server
git switch nex/feat/notary-server
Sign in to join this conversation.
No reviewers
No milestone
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
continuwuation/continuwuity!2314
No description provided.