From 6029db28e244d9a95375386cd2b9a07d3a7e0540 Mon Sep 17 00:00:00 2001 From: Kegan Dougal <7190048+kegsay@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:33:38 +0100 Subject: [PATCH 1/4] Ensure the create event is cached prior to sorting --- stateresolutionv2.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/stateresolutionv2.go b/stateresolutionv2.go index 770d9282..10c7bc6c 100644 --- a/stateresolutionv2.go +++ b/stateresolutionv2.go @@ -391,17 +391,26 @@ func ResolveStateConflictsV2New( // using Kahn's algorithm in order to topologically order them. The // result array of events will be sorted so that "earlier" events appear // first. +// FIXME: this function does not sort correctly because it doesn't lookup PL events +// correctly, meaning it will sort incorrectly for PL tiebreaks. func ReverseTopologicalOrdering(input []PDU, order TopologicalOrder) []PDU { - r := stateResolverV2{} + r := stateResolverV2{ + resolvedCreate: getCreateEvent(input), + } return r.reverseTopologicalOrdering(input, order) } +// TODO: Remove this function. Use ReverseTopologicalOrdering. // HeaderedReverseTopologicalOrdering takes a set of input events and sorts // them using Kahn's algorithm in order to topologically order them. The // result array of events will be sorted so that "earlier" events appear // first. +// FIXME: this function does not sort correctly because it doesn't lookup PL events +// correctly, meaning it will sort incorrectly for PL tiebreaks. func HeaderedReverseTopologicalOrdering(events []PDU, order TopologicalOrder) []PDU { - r := stateResolverV2{} + r := stateResolverV2{ + resolvedCreate: getCreateEvent(events), + } input := make([]PDU, len(events)) for i := range events { unwrapped := events[i] @@ -414,6 +423,15 @@ func HeaderedReverseTopologicalOrdering(events []PDU, order TopologicalOrder) [] return result } +func getCreateEvent(input []PDU) PDU { + for _, ev := range input { + if ev.Type() == spec.MRoomCreate && ev.StateKeyEquals("") { + return ev + } + } + return nil +} + // isControlEvent returns true if the event meets the criteria for being classed // as a "control" event for reverse topological sorting. If not then the event // will be mainline sorted. From 3c641bb19714c015e99c5cdaf794ff98cea782d5 Mon Sep 17 00:00:00 2001 From: Kegan Dougal <7190048+kegsay@users.noreply.github.com> Date: Wed, 13 Aug 2025 14:11:15 +0100 Subject: [PATCH 2/4] Fix invites in v12 rooms They would previously include the create event because `stateNeeded` returns the state needed for auth purposes, not for setting `auth_events`. --- performinvite.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/performinvite.go b/performinvite.go index 69ea5152..5bc7e2ae 100644 --- a/performinvite.go +++ b/performinvite.go @@ -112,6 +112,9 @@ func PerformInvite(ctx context.Context, input PerformInviteInput, fedClient Fede if len(stateNeeded.Tuples()) == 0 { return nil, spec.InternalServerError{} } + if stateNeeded.Create && verImpl.DomainlessRoomIDs() { + stateNeeded.Create = false + } latestEvents, err := input.EventQuerier(ctx, input.RoomID, stateNeeded.Tuples()) if err != nil { From 908a63a3eeeae3fa791e81dd76ed4d7a189a0d8e Mon Sep 17 00:00:00 2001 From: Kegan Dougal <7190048+kegsay@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:43:41 +0100 Subject: [PATCH 3/4] Debug logging --- performinvite.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/performinvite.go b/performinvite.go index 5bc7e2ae..1dd8cf1b 100644 --- a/performinvite.go +++ b/performinvite.go @@ -115,6 +115,7 @@ func PerformInvite(ctx context.Context, input PerformInviteInput, fedClient Fede if stateNeeded.Create && verImpl.DomainlessRoomIDs() { stateNeeded.Create = false } + fmt.Println("debug-invite:: stateNeeded.Create=", stateNeeded.Create, "domainless=", verImpl.DomainlessRoomIDs()) latestEvents, err := input.EventQuerier(ctx, input.RoomID, stateNeeded.Tuples()) if err != nil { @@ -155,6 +156,8 @@ func PerformInvite(ctx context.Context, input PerformInviteInput, fedClient Fede ) return spec.Forbidden(err.Error()) } + c, e := authEventProvider.Create() + fmt.Println("debug-invite:: checkEventAllowed authEventProvider create=", c, "err=", e) // Check if the event is allowed. if err = Allowed(inviteEvent, authEventProvider, input.UserIDQuerier); err != nil { From 06887dd976e0d11003b6c728c5f2f206a9f9655f Mon Sep 17 00:00:00 2001 From: Kegan Dougal <7190048+kegsay@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:59:41 +0100 Subject: [PATCH 4/4] Revert "Debug logging" This reverts commit 908a63a3eeeae3fa791e81dd76ed4d7a189a0d8e. --- performinvite.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/performinvite.go b/performinvite.go index 1dd8cf1b..5bc7e2ae 100644 --- a/performinvite.go +++ b/performinvite.go @@ -115,7 +115,6 @@ func PerformInvite(ctx context.Context, input PerformInviteInput, fedClient Fede if stateNeeded.Create && verImpl.DomainlessRoomIDs() { stateNeeded.Create = false } - fmt.Println("debug-invite:: stateNeeded.Create=", stateNeeded.Create, "domainless=", verImpl.DomainlessRoomIDs()) latestEvents, err := input.EventQuerier(ctx, input.RoomID, stateNeeded.Tuples()) if err != nil { @@ -156,8 +155,6 @@ func PerformInvite(ctx context.Context, input PerformInviteInput, fedClient Fede ) return spec.Forbidden(err.Error()) } - c, e := authEventProvider.Create() - fmt.Println("debug-invite:: checkEventAllowed authEventProvider create=", c, "err=", e) // Check if the event is allowed. if err = Allowed(inviteEvent, authEventProvider, input.UserIDQuerier); err != nil {