Try to modify MSC4311 test to meet new proposal#796
Conversation
| must.MatchGJSON(t, ev, | ||
| match.JSONKeyPresent("origin_server_ts"), | ||
| ) | ||
| srv.Mux().HandleFunc("/_matrix/federation/v2/invite/{roomID}/{eventID}", srv.ValidFederationRequest(t, func(fr *fclient.FederationRequest, pathParams map[string]string) util.JSONResponse { |
There was a problem hiding this comment.
You should be able to alternatively use:
srv := federation.NewServer(t, deployment,
federation.HandleInviteRequests(func(p gomatrixserverlib.PDU) {
// checks here
}),
federation.HandleKeyRequests(),
federation.HandleMakeSendJoinRequests(),
federation.HandleTransactionRequests(nil, nil),
)There was a problem hiding this comment.
I went down this route but the problem is that federation.HandleInviteRequests(...) doesn't allow you to inspect the invite_room_state yet. It would have to be updated to pass in the full invite request to the callback.
And gomatrixserverlib needs to be updated to handle the new world where invite_room_state can be stripped state or full PDUs.
We could have an infallible InviteV2Request.StrippedInviteRoomState() that would give a view of stripped state regardless of whether we were passed stripped or full PDU's (we can derive stripped state from the full PDU's). And then a fallible InviteV2Request.FullInviteRoomState() that would return an error if the homeserver didn't pass us full PDUs.
We would also need to update IRoomVersion to add new fields like CreateEventRequiredInInviteRoomState and (full PDU's can happen in any room version) so we can conditionally apply this behavior. Or maybe the flags could be combined as FullPDUInviteRoomStateMSC4311InviteRoomState
If any of the events are not a PDU, not for the room ID specified, or fail signature checks, or the
m.room.createevent is missing, the receiving server MAY respond to invites with a400 M_MISSING_PARAMstandard Matrix error (new to the endpoint). For invites to room version 12+ rooms, servers SHOULD rather than MAY respond to such requests with400 M_MISSING_PARAM.
| match.JSONArrayEach("invite_room_state", func(event gjson.Result) error { | ||
| // Each event should have extra fields `origin_server_ts` that indicate we're | ||
| // seeing a full PDU and not just a "stripped state event" | ||
| return should.MatchGJSON(event, match.JSONKeyPresent("origin_server_ts")) | ||
| }), |
There was a problem hiding this comment.
This currently fails in Synapse because it just pulls invite_room_state from the the unsigned part of the PDU which will be the stripped state client version, see synapse/federation/federation_client.py#L1361
Example flawed /_matrix/federation/v2/invite/{roomID}/{eventID} request body from Synapse
{
"event": {
"auth_events": [
"$3-FVPb1HO_ZyxolbnthZ8qTVEMXyZ6px4qUdrL0exII",
"$hRMnmEtlMElF2pqbd23ccVSfAIUq-Dqo9kxORAbs2Pk",
"$luBrxrHgZcSqpdm5UMAXtGKxCvmOwGAHJrZ0iMeWrdw"
],
"content": {
"membership": "invite"
},
"depth": 6,
"hashes": {
"sha256": "xBOaaPtS1jAtu/qsWiBIXFZqDdOm6zI8R+RVgXfhm00"
},
"origin_server_ts": 1777676386564,
"prev_events": [
"$VoTAQZqsV4zWnRi3Uh9n42ioJ4J74UvwMoZuHNiHWU4"
],
"room_id": "!gvlLh8tsK9LSCdF8y56dVfErfUiw7lZnLQ8JTB_kih4",
"sender": "@user-1-alice:hs1",
"signatures": {
"hs1": {
"ed25519:a_NKNg": "xS/15iTHLn3I65oaTdVRMFBrs+ASbKp9Lm9GM8oLoKlD3ZUwtuBP2pyN/tdUXgraKnRNDU1b3PLxpXYzsLGkCQ"
}
},
"state_key": "@bob:host.docker.internal:44453",
"type": "m.room.member",
"unsigned": {
"age": 11,
"invite_room_state": [
{
"auth_events": [],
"content": {
"room_version": "12"
},
"depth": 1,
"hashes": {
"sha256": "vVkUaUxHUum571Kj4D0vo85iS2dssrPpILSm3XnELpc"
},
"origin_server_ts": 1777676385521,
"prev_events": [],
"sender": "@user-1-alice:hs1",
"signatures": {
"hs1": {
"ed25519:a_NKNg": "m7pf3WIpaGZEgTR85+L+ewSY88eBXJSGecOXXJmLudEFq4mGxR4MBw6/x9+xMTz4byo+z0a+0h4IcvvSyYhiAA"
}
},
"state_key": "",
"type": "m.room.create",
"unsigned": {
"age_ts": 1777676385521
}
},
{
"content": {
"join_rule": "public"
},
"sender": "@user-1-alice:hs1",
"state_key": "",
"type": "m.room.join_rules"
},
{
"content": {
"displayname": "user-1-alice",
"membership": "join"
},
"sender": "@user-1-alice:hs1",
"state_key": "@user-1-alice:hs1",
"type": "m.room.member"
}
]
}
},
"invite_room_state": [
{
"auth_events": [],
"content": {
"room_version": "12"
},
"depth": 1,
"hashes": {
"sha256": "vVkUaUxHUum571Kj4D0vo85iS2dssrPpILSm3XnELpc"
},
"origin_server_ts": 1777676385521,
"prev_events": [],
"sender": "@user-1-alice:hs1",
"signatures": {
"hs1": {
"ed25519:a_NKNg": "m7pf3WIpaGZEgTR85+L+ewSY88eBXJSGecOXXJmLudEFq4mGxR4MBw6/x9+xMTz4byo+z0a+0h4IcvvSyYhiAA"
}
},
"state_key": "",
"type": "m.room.create",
"unsigned": {
"age_ts": 1777676385521
}
},
{
"content": {
"join_rule": "public"
},
"sender": "@user-1-alice:hs1",
"state_key": "",
"type": "m.room.join_rules"
},
{
"content": {
"displayname": "user-1-alice",
"membership": "join"
},
"sender": "@user-1-alice:hs1",
"state_key": "@user-1-alice:hs1",
"type": "m.room.member"
}
],
"room_version": "12"
}There was a problem hiding this comment.
Test passes with Synapse with the changes from element-hq/synapse#19723 ✅
COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -run TestMSC4311FullEventsOnStrippedStateFederation
| var roomVersion gomatrixserverlib.RoomVersion | ||
| if err := json.Unmarshal([]byte(rawRoomVersion), &roomVersion); err != nil { | ||
| t.Fatalf("failed to parse room version: %s", err) |
There was a problem hiding this comment.
Better way to get a gomatrixserverlib.RoomVersion from a room version string?
But it doesn't seem possible to see. For example, Synapse strips it out when trying to view events, https://github.com/element-hq/synapse/blob/6100f6e4f7fb0c72f1ae2802683ebc811c0e3a77/synapse/events/utils.py#L590-L596
| // TODO: Test events not full PDU's | ||
|
|
||
| // TODO: Test events not from the same room | ||
|
|
||
| // TODO: Test invalid signatures/hashes |
There was a problem hiding this comment.
Something for future PRs
| // > error (new to the endpoint). For invites to room version 12+ rooms, servers | ||
| // > SHOULD rather than MAY respond to such requests with `400 M_MISSING_PARAM`. | ||
| func TestMSC4311RejectInvalidStrippedStateFederation(t *testing.T) { | ||
| runtime.SkipIf(t, runtime.Synapse) // FIXME: Run these tests after 2027-06-01 |
There was a problem hiding this comment.
Also cross-linked this in the Synapse codebase (see element-hq/synapse#19723)
Update MSC4311 tests to conform to the spec.
"I have no idea what I'm doing" disclaimer goes heretaken over by @MadLittleModsFor
element-hq/synapse#18822element-hq/synapse#19723Dev notes